#pragma once
#ifndef CONFIG_HPP
#define CONFIG_HPP
#include <string>
#include <stdexcept>
#include <vector>
#include <boost/program_options/variables_map.hpp>
#include "Misc.hpp"

struct ConfigErrorCmdLine : public std::invalid_argument {
	ConfigErrorCmdLine(const std::exception &e) : std::invalid_argument(e.what()) {};
	ConfigErrorCmdLine(const std::string &s) : std::invalid_argument(s) {};
};
struct ConfigErrorConfigFile : public std::invalid_argument {
	ConfigErrorConfigFile(const std::exception &e) : std::invalid_argument(e.what()) {};
	ConfigErrorConfigFile(const std::string &s) : std::invalid_argument(s) {}
};
struct ConfigErrorValidate : public std::invalid_argument {
	ConfigErrorValidate(const std::string &s) : std::invalid_argument(s) {};
};

class Config {
public:
	Config(int argc, char **argv);
	~Config();

	// loadConfig and loadConfigFile return false when app should exit(normally)
	bool loadConfig() throw(ConfigErrorCmdLine, ConfigErrorConfigFile);
	bool loadConfigFile(const std::string &filename) throw(ConfigErrorCmdLine, ConfigErrorConfigFile);

	// Get any value. Slow, can throw and badass
	template <typename T> inline const T &getValue_Cast(const std::string &key) const throw(std::bad_cast) {
		return vm[key].as<T>();
	}

	inline const misc::IpAddrList &MysqlAuthServers() const {
		return _MysqlAuthServers;
	}
private:
	misc::IpAddrList _MysqlAuthServers;

	int _argc;
	char **_argv;
	std::string config_file;
	boost::program_options::variables_map vm;
};

#endif
